package v2db

import (
	"fmt"
	"github.com/elliotchance/orderedmap/v2"
	"os"
	"regexp"
	"strconv"
	"strings"
)

// parseCreateTableSQL 解析CREATE TABLE SQL语句
func parseCreateTableSQL(sql string) (string, *orderedmap.OrderedMap[string, string]) {
	re := regexp.MustCompile(`CREATE TABLE (\w+) \((.+)\)`)
	matches := re.FindStringSubmatch(sql)
	if len(matches) != 3 {
		panic("Invalid CREATE TABLE statement")
	}
	tableName := matches[1]
	schema := orderedmap.NewOrderedMap[string, string]()
	columns := strings.Split(matches[2], ",")
	for _, column := range columns {
		col := strings.TrimSpace(column)
		parts := strings.Split(col, " ")
		if len(parts) != 2 {
			panic("Invalid column definition")
		}
		schema.Set(parts[0], parts[1])
	}
	return tableName, schema
}

// parseInsertSQL 解析INSERT INTO SQL语句
func parseInsertSQL(sql string) (string, []interface{}) {
	re := regexp.MustCompile(`INSERT INTO (\w+) VALUES \((.+)\)`)
	matches := re.FindStringSubmatch(sql)
	if len(matches) != 3 {
		panic("Invalid INSERT INTO statement")
	}
	tableName := matches[1]
	valueStrings := strings.Split(matches[2], ",")
	values := make([]interface{}, len(valueStrings))
	for i, v := range valueStrings {
		v = strings.Trim(v, "'")
		if v == "NULL" {
			values[i] = nil
		} else if val, err := strconv.Atoi(v); err == nil {
			values[i] = val // Will be converted to int in executeSQL
		} else if val, err := strconv.ParseInt(v, 10, 64); err == nil {
			values[i] = val // Will be converted to int64 in executeSQL
		} else {
			values[i] = v // Will be treated as a string
		}
	}
	return tableName, values
}

// parseUpdateSQL 解析UPDATE SQL语句
func parseUpdateSQL(sql string) (string, map[string]interface{}, map[string]interface{}) {
	re := regexp.MustCompile(`UPDATE (\w+) SET (.+) WHERE (.+)`)
	matches := re.FindStringSubmatch(sql)
	if len(matches) != 4 {
		panic("Invalid UPDATE statement")
	}
	tableName := matches[1]
	setClause := strings.Split(matches[2], ",")
	setMap := make(map[string]interface{})
	for _, set := range setClause {
		parts := strings.Split(set, "=")
		if len(parts) != 2 {
			panic("Invalid SET clause")
		}
		setMap[parts[0]] = parts[1]
	}
	whereMap := make(map[string]interface{})
	parts := strings.Split(matches[3], "=")
	if len(parts) != 2 {
		panic("Invalid WHERE clause")
	}
	whereMap[parts[0]] = parts[1]
	return tableName, setMap, whereMap
}

// parseDeleteSQL 解析DELETE SQL语句
func parseDeleteSQL(sql string) (string, map[string]interface{}) {
	re := regexp.MustCompile(`DELETE FROM (\w+) WHERE (.+)`)
	matches := re.FindStringSubmatch(sql)
	if len(matches) != 3 {
		panic("Invalid DELETE statement")
	}
	tableName := matches[1]
	parts := strings.Split(matches[2], "=")
	if len(parts) != 2 {
		panic("Invalid WHERE clause")
	}
	return tableName, map[string]interface{}{parts[0]: parts[1]}
}

// executeSQL 执行SQL语句
func (db *LSMDatabase) executeSQL(sql string) {
	trimmedSQL := strings.TrimSpace(sql)
	switch {
	case strings.HasPrefix(trimmedSQL, "SELECT"):
		tableName, whereClause, groupClause := parseSelectSQL(trimmedSQL)
		allRows := db.selectAllRows(tableName)
		filteredRows, err := db.filterRows(allRows, whereClause)
		if err != nil {
			fmt.Printf("Error filtering rows: %v\n", err)
			return
		}
		groupedRows, err := db.groupRows(filteredRows, groupClause)
		if err != nil {
			fmt.Printf("Error grouping rows: %v\n", err)
			return
		}
		db.printGroupedRows(groupedRows)
	case strings.HasPrefix(trimmedSQL, "CREATE TABLE"):
		tableName, schema := parseCreateTableSQL(trimmedSQL)
		db.CreateTable(tableName, schema)
		fmt.Printf("Table '%s' created successfully.\n", tableName)
	case strings.HasPrefix(trimmedSQL, "INSERT INTO"):
		tableName, values := parseInsertSQL(trimmedSQL)
		if db.Memtable.Name != tableName {
			fmt.Printf("Table '%s' does not exist.\n", tableName)
			return
		}
		// 确保插入的值的数量与表的列的数量匹配
		if len(values) != db.Memtable.Schema.Len() {
			fmt.Printf("The number of values does not match the number of columns in table '%s'.\n", tableName)
			return
		}
		row := &Row{Values: make(map[string]interface{})}
		colNames := make([]string, 0, db.Memtable.Schema.Len())
		for _, colName := range db.Memtable.Schema.Keys() {
			colNames = append(colNames, colName)
		}
		for i, colName := range colNames {
			value := values[i]
			colType, _ := db.Memtable.Schema.Get(colName)
			switch colType {
			case "STRING":
				row.Values[colName] = value.(string)
			case "INT":
				if intValue, ok := value.(int); ok {
					row.Values[colName] = intValue
				} else if int64Value, ok := value.(int64); ok {
					row.Values[colName] = int(int64Value)
				} else {
					fmt.Printf("Invalid INT value for column '%s'.\n", colName)
					return
				}
			default:
				fmt.Printf("Unsupported column type for column '%s'.\n", colName)
				return
			}
		}
		db.Memtable.Rows = append(db.Memtable.Rows, row)
		fmt.Printf("Row inserted into '%s' successfully.\n", tableName)
	case strings.HasPrefix(trimmedSQL, "UPDATE"):
		tableName, setMap, whereMap := parseUpdateSQL(trimmedSQL)
		for _, row := range db.Memtable.Rows {
			for key, value := range whereMap {
				if row.Values[key] == value {
					for setKey, setValue := range setMap {
						row.Values[setKey] = setValue
					}
				}
			}
		}
		fmt.Printf("Rows in '%s' updated successfully.\n", tableName)
	case strings.HasPrefix(trimmedSQL, "DELETE FROM"):
		tableName, whereMap := parseDeleteSQL(trimmedSQL)
		var newRows []*Row
		for _, row := range db.Memtable.Rows {
			match := true
			for key, value := range whereMap {
				if row.Values[key] != value {
					match = false
					break
				}
			}
			if !match {
				newRows = append(newRows, row)
			}
		}
		db.Memtable.Rows = newRows
		fmt.Printf("Rows in '%s' deleted successfully.\n", tableName)

	default:
		fmt.Printf("Unsupported SQL statement: %s\n", trimmedSQL)
	}
}

// selectAllRows 选择所有行
func (db *LSMDatabase) selectAllRows(tableName string) []*Row {
	var allRows []*Row
	for _, sstable := range db.SSTables {
		if sstable.Name == tableName {
			allRows = append(allRows, sstable.Rows...)
		}
	}
	allRows = append(allRows, db.Memtable.Rows...)
	return allRows
}

// filterRows 根据条件过滤行
func (db *LSMDatabase) filterRows(rows []*Row, whereClause string) ([]*Row, error) {
	column, value := parseWhereClause(whereClause)
	var filteredRows []*Row
	for _, row := range rows {
		if fmt.Sprintf("%v", row.Values[column]) == value.(string) {
			filteredRows = append(filteredRows, row)
		}
	}
	return filteredRows, nil
}

// groupRows 根据分组条件分组行
func (db *LSMDatabase) groupRows(rows []*Row, groupClause string) (map[string][]*Row, error) {
	groupedRows := make(map[string][]*Row)
	for _, row := range rows {
		groupKey := fmt.Sprintf("%v", row.Values[groupClause])
		groupedRows[groupKey] = append(groupedRows[groupKey], row)
	}
	return groupedRows, nil
}

// printGroupedRows 打印分组后的行
func (db *LSMDatabase) printGroupedRows(groupedRows map[string][]*Row) {
	for groupKey, rows := range groupedRows {
		fmt.Printf("Group by '%s':\n", groupKey)
		for _, row := range rows {
			fmt.Printf("%v\n", row.Values)
		}
	}
}

// parseWhereClause 解析 WHERE 子句
func parseWhereClause(whereClause string) (string, interface{}) {
	matches := strings.Split(whereClause, "=")
	return matches[0], matches[1]
}

// parseSelectSQL 解析SELECT SQL语句
func parseSelectSQL(sql string) (string, string, string) {
	re := regexp.MustCompile(`SELECT \* FROM (\w+) WHERE (.+) GROUP BY (.+)`)
	matches := re.FindStringSubmatch(sql)
	if len(matches) != 4 {
		panic("Invalid SELECT statement")
	}
	return matches[1], matches[2], matches[3]
}

func runSqlParser() {
	// 创建数据目录
	dataDir := "./data"
	os.MkdirAll(dataDir, os.ModePerm)

	db := NewLSMDatabase(dataDir)

	// 执行SQL语句
	sqlStatements := []string{
		"CREATE TABLE user (name STRING, age INT, sex STRING)",
		"INSERT INTO user VALUES ('Alice',31,'Female')",
		"INSERT INTO user VALUES ('Bob',25,'Male')",
		"UPDATE user SET age=31 WHERE name='Alice'",
		"DELETE FROM user WHERE age=25",
	}

	for _, sql := range sqlStatements {
		db.executeSQL(sql)
	}
	// 将Memtable数据写入SSTable
	db.FlushMemtable()
	db.executeSQL("SELECT * FROM user WHERE age=31 GROUP BY sex")
}
